import * as fs from 'fs';
import * as path from 'path';
import { JavaParser } from '../utils/JavaParser.js';

export interface ServiceSplitResult {
  success: boolean;
  message: string;
  generatedFiles: string[];
  generatedServices: Array<{
    serviceName: string;
    description: string;
    methods: string[];
    dependencies: string[];
  }>;
  errors?: string[];
}

export interface ServiceMethod {
  name: string;
  startLine: number;
  endLine: number;
  content: string;
  businessDomain: string;
  dependencies: Set<string>;
  annotations: string[];
}

/**
 * Service拆分器 - 将大型Service类拆分为多个专门的Service
 */
export class ServiceSplitter {

  async splitLargeService(filePath: string, splitStrategy: string = 'by_business_domain'): Promise<ServiceSplitResult> {
    const result: ServiceSplitResult = {
      success: false,
      message: '',
      generatedFiles: [],
      generatedServices: [],
      errors: []
    };

    try {
      console.error(`[ServiceSplitter] 开始拆分Service: ${filePath}, 策略: ${splitStrategy}`);
      
      const fileContent = fs.readFileSync(filePath, 'utf-8');
      const className = this.extractClassName(fileContent);
      
      if (!className) {
        result.errors?.push('无法识别类名');
        result.message = '无法识别类名';
        return result;
      }

      console.error(`[ServiceSplitter] 识别到类名: ${className}`);

      // 解析Service结构
      const serviceStructure = this.analyzeServiceStructure(fileContent);
      console.error(`[ServiceSplitter] 找到 ${serviceStructure.methods.length} 个方法`);

      // 根据策略进行拆分
      let servicePlan: Map<string, ServiceMethod[]>;
      
      switch (splitStrategy) {
        case 'by_business_domain':
          servicePlan = this.splitByBusinessDomain(serviceStructure.methods);
          break;
        case 'by_method_group':
          servicePlan = this.splitByMethodGroup(serviceStructure.methods);
          break;
        case 'by_dependency':
          servicePlan = this.splitByDependency(serviceStructure.methods, serviceStructure.dependencies);
          break;
        default:
          servicePlan = this.splitByBusinessDomain(serviceStructure.methods);
      }

      console.error(`[ServiceSplitter] 计划拆分为 ${servicePlan.size} 个Service`);

      // 生成新的Service文件
      const baseDir = path.dirname(filePath);
      const packageName = this.extractPackageName(fileContent);
      const originalImports = this.extractImports(fileContent);
      const classAnnotations = this.extractClassAnnotations(fileContent);
      const fields = this.extractFields(fileContent);

      for (const [serviceName, methods] of servicePlan) {
        try {
          const newServiceContent = this.generateServiceFile(
            serviceName,
            packageName,
            originalImports,
            classAnnotations,
            fields,
            methods,
            serviceStructure.helperMethods
          );

          const newFilePath = path.join(baseDir, `${serviceName}.java`);
          fs.writeFileSync(newFilePath, newServiceContent, 'utf-8');
          
          result.generatedFiles.push(newFilePath);
          result.generatedServices.push({
            serviceName,
            description: this.generateServiceDescription(serviceName, methods),
            methods: methods.map(m => m.name),
            dependencies: Array.from(new Set(methods.flatMap(m => Array.from(m.dependencies))))
          });

          console.error(`[ServiceSplitter] 生成Service文件: ${newFilePath}`);
        } catch (error) {
          result.errors?.push(`生成${serviceName}失败: ${error}`);
        }
      }

      if (result.generatedFiles.length > 0) {
        result.success = true;
        result.message = `成功拆分 ${className} 为 ${result.generatedFiles.length} 个Service`;
      } else {
        result.message = '没有生成任何Service文件';
      }

    } catch (error) {
      result.errors?.push(`拆分Service失败: ${error}`);
      result.message = `拆分Service失败: ${error}`;
      console.error(`[ServiceSplitter] 错误:`, error);
    }

    return result;
  }

  private extractClassName(content: string): string | null {
    const match = content.match(/public\s+class\s+(\w+)/);
    return match ? match[1] : null;
  }

  private extractPackageName(content: string): string {
    const match = content.match(/package\s+([^;]+);/);
    return match ? match[1] : 'com.example.service';
  }

  private extractImports(content: string): string[] {
    const imports: string[] = [];
    const lines = content.split('\n');
    
    for (const line of lines) {
      const trimmed = line.trim();
      if (trimmed.startsWith('import ') && trimmed.endsWith(';')) {
        imports.push(trimmed);
      }
    }
    
    return imports;
  }

  private extractClassAnnotations(content: string): string[] {
    const annotations: string[] = [];
    const lines = content.split('\n');
    
    for (let i = 0; i < lines.length; i++) {
      const trimmed = lines[i].trim();
      if (trimmed.startsWith('@') && !trimmed.includes('(')) {
        annotations.push(trimmed);
      } else if (trimmed.startsWith('public class ')) {
        break;
      }
    }
    
    return annotations;
  }

  private extractFields(content: string): string[] {
    const fields: string[] = [];
    const lines = content.split('\n');
    let inClass = false;
    let braceCount = 0;
    
    for (const line of lines) {
      const trimmed = line.trim();
      
      if (trimmed.includes('public class ')) {
        inClass = true;
        continue;
      }
      
      if (!inClass) continue;
      
      // 计算大括号
      for (const char of line) {
        if (char === '{') braceCount++;
        if (char === '}') braceCount--;
      }
      
      // 只在类的第一层级寻找字段
      if (braceCount === 1 && (trimmed.startsWith('@Autowired') || 
          trimmed.startsWith('private ') || 
          trimmed.startsWith('public ') ||
          trimmed.startsWith('protected ') ||
          trimmed.startsWith('static '))) {
        
        if (trimmed.includes(' ') && (trimmed.endsWith(';') || trimmed.includes('='))) {
          fields.push(line);
        }
      }
      
      // 遇到第一个方法就停止
      if (braceCount === 1 && (trimmed.includes('public ') || trimmed.includes('private ')) 
          && trimmed.includes('(') && trimmed.includes(')')) {
        break;
      }
    }
    
    return fields;
  }

  private analyzeServiceStructure(content: string): {
    methods: ServiceMethod[],
    dependencies: Set<string>,
    helperMethods: ServiceMethod[]
  } {
    const methods: ServiceMethod[] = [];
    const helperMethods: ServiceMethod[] = [];
    const dependencies = new Set<string>();
    
    const lines = content.split('\n');
    
    for (let i = 0; i < lines.length; i++) {
      const line = lines[i];
      
      // 检测方法定义
      if (this.isMethodDefinition(line)) {
        const methodName = this.extractMethodName(line);
        if (methodName) {
          const methodInfo = JavaParser.findMethodBounds(content, methodName);
          if (methodInfo) {
            const methodContent = lines.slice(methodInfo.startLine - 1, methodInfo.endLine).join('\n');
            const businessDomain = this.identifyBusinessDomain(methodName, methodContent);
            const methodDependencies = this.extractMethodDependencies(methodContent);
            const annotations = this.extractMethodAnnotations(lines, methodInfo.startLine - 1);
            
            const serviceMethod: ServiceMethod = {
              name: methodName,
              startLine: methodInfo.startLine,
              endLine: methodInfo.endLine,
              content: methodContent,
              businessDomain,
              dependencies: methodDependencies,
              annotations
            };
            
            // 区分业务方法和辅助方法
            if (this.isHelperMethod(methodName, line)) {
              helperMethods.push(serviceMethod);
            } else {
              methods.push(serviceMethod);
            }
            
            methodDependencies.forEach(dep => dependencies.add(dep));
          }
        }
      }
    }
    
    return { methods, dependencies, helperMethods };
  }

  private isMethodDefinition(line: string): boolean {
    const trimmed = line.trim();
    return (trimmed.includes('public ') || trimmed.includes('private ') || trimmed.includes('protected ')) &&
           trimmed.includes('(') && 
           (trimmed.includes('{') || trimmed.endsWith(')'));
  }

  private extractMethodName(line: string): string | null {
    const match = line.match(/\b(\w+)\s*\(/);
    return match ? match[1] : null;
  }

  private isHelperMethod(methodName: string, line: string): boolean {
    return line.trim().startsWith('private ') || 
           methodName.startsWith('calculate') ||
           methodName.startsWith('generate') ||
           methodName.startsWith('validate') ||
           methodName.startsWith('extract') ||
           methodName.startsWith('format') ||
           methodName.startsWith('convert');
  }

  private identifyBusinessDomain(methodName: string, methodContent: string): string {
    const name = methodName.toLowerCase();
    const content = methodContent.toLowerCase();
    
    // 用户相关
    if (name.includes('user') || name.includes('register') || name.includes('login') || 
        content.includes('user') || content.includes('profile')) {
      return 'User';
    }
    
    // 订单相关
    if (name.includes('order') || name.includes('cart') || name.includes('item') ||
        content.includes('order') || content.includes('cart')) {
      return 'Order';
    }
    
    // 商品相关
    if (name.includes('product') || name.includes('inventory') || name.includes('stock') ||
        content.includes('product') || content.includes('inventory')) {
      return 'Product';
    }
    
    // 支付相关
    if (name.includes('payment') || name.includes('pay') || name.includes('alipay') || name.includes('wechat') ||
        content.includes('payment') || content.includes('alipay') || content.includes('wechat')) {
      return 'Payment';
    }
    
    // 通知相关
    if (name.includes('notification') || name.includes('notify') || name.includes('email') || name.includes('sms') ||
        content.includes('notification') || content.includes('email') || content.includes('sms')) {
      return 'Notification';
    }
    
    // 统计相关
    if (name.includes('statistics') || name.includes('stats') || name.includes('report') ||
        content.includes('statistics') || content.includes('stats')) {
      return 'Statistics';
    }
    
    return 'Common';
  }

  private extractMethodDependencies(methodContent: string): Set<string> {
    const dependencies = new Set<string>();
    
    // 检测@Autowired依赖
    const autowiredMatches = methodContent.match(/@Autowired\s+private\s+(\w+)/g);
    if (autowiredMatches) {
      autowiredMatches.forEach(match => {
        const dep = match.match(/private\s+(\w+)/)?.[1];
        if (dep) dependencies.add(dep);
      });
    }
    
    // 检测Repository调用
    const repoMatches = methodContent.match(/(\w+Repository)\./g);
    if (repoMatches) {
      repoMatches.forEach(match => {
        const repo = match.replace('.', '');
        dependencies.add(repo);
      });
    }
    
    // 检测Service调用
    const serviceMatches = methodContent.match(/(\w+Service)\./g);
    if (serviceMatches) {
      serviceMatches.forEach(match => {
        const service = match.replace('.', '');
        dependencies.add(service);
      });
    }
    
    // 检测其他常见依赖
    if (methodContent.includes('redisTemplate')) dependencies.add('RedisTemplate');
    if (methodContent.includes('rabbitTemplate')) dependencies.add('RabbitTemplate');
    if (methodContent.includes('emailService')) dependencies.add('EmailService');
    if (methodContent.includes('smsService')) dependencies.add('SmsService');
    
    return dependencies;
  }

  private extractMethodAnnotations(lines: string[], methodStartIndex: number): string[] {
    const annotations: string[] = [];
    
    for (let i = methodStartIndex - 1; i >= 0; i--) {
      const trimmed = lines[i].trim();
      if (trimmed.startsWith('@')) {
        annotations.unshift(trimmed);
      } else if (trimmed !== '' && !trimmed.startsWith('//') && !trimmed.startsWith('*')) {
        break;
      }
    }
    
    return annotations;
  }

  private splitByBusinessDomain(methods: ServiceMethod[]): Map<string, ServiceMethod[]> {
    const servicePlan = new Map<string, ServiceMethod[]>();
    
    methods.forEach(method => {
      const serviceName = `${method.businessDomain}Service`;
      
      if (!servicePlan.has(serviceName)) {
        servicePlan.set(serviceName, []);
      }
      
      servicePlan.get(serviceName)!.push(method);
    });
    
    return servicePlan;
  }

  private splitByMethodGroup(methods: ServiceMethod[]): Map<string, ServiceMethod[]> {
    const servicePlan = new Map<string, ServiceMethod[]>();
    
    // 按方法前缀分组
    methods.forEach(method => {
      let groupName = 'CommonService';
      
      if (method.name.startsWith('create') || method.name.startsWith('save')) {
        groupName = 'CreationService';
      } else if (method.name.startsWith('get') || method.name.startsWith('find') || method.name.startsWith('search')) {
        groupName = 'QueryService';
      } else if (method.name.startsWith('update') || method.name.startsWith('modify')) {
        groupName = 'UpdateService';
      } else if (method.name.startsWith('delete') || method.name.startsWith('remove')) {
        groupName = 'DeletionService';
      } else if (method.name.startsWith('process') || method.name.startsWith('handle')) {
        groupName = 'ProcessingService';
      } else if (method.name.startsWith('send') || method.name.startsWith('notify')) {
        groupName = 'NotificationService';
      }
      
      if (!servicePlan.has(groupName)) {
        servicePlan.set(groupName, []);
      }
      
      servicePlan.get(groupName)!.push(method);
    });
    
    return servicePlan;
  }

  private splitByDependency(methods: ServiceMethod[], allDependencies: Set<string>): Map<string, ServiceMethod[]> {
    const servicePlan = new Map<string, ServiceMethod[]>();
    
    // 根据主要依赖分组
    methods.forEach(method => {
      let serviceName = 'CommonService';
      
      if (method.dependencies.has('UserRepository')) {
        serviceName = 'UserService';
      } else if (method.dependencies.has('OrderRepository')) {
        serviceName = 'OrderService';
      } else if (method.dependencies.has('ProductRepository')) {
        serviceName = 'ProductService';
      } else if (method.dependencies.has('PaymentRepository')) {
        serviceName = 'PaymentService';
      } else if (method.dependencies.has('NotificationRepository')) {
        serviceName = 'NotificationService';
      } else if (method.dependencies.has('EmailService') || method.dependencies.has('SmsService')) {
        serviceName = 'CommunicationService';
      }
      
      if (!servicePlan.has(serviceName)) {
        servicePlan.set(serviceName, []);
      }
      
      servicePlan.get(serviceName)!.push(method);
    });
    
    return servicePlan;
  }

  private generateServiceFile(
    serviceName: string,
    packageName: string,
    originalImports: string[],
    classAnnotations: string[],
    fields: string[],
    methods: ServiceMethod[],
    helperMethods: ServiceMethod[]
  ): string {
    const lines: string[] = [];
    
    // Package声明
    lines.push(`package ${packageName};`);
    lines.push('');
    
    // Imports
    const requiredImports = this.getRequiredImports(methods, helperMethods);
    const filteredImports = originalImports.filter(imp => 
      requiredImports.some(req => imp.includes(req))
    );
    
    // 添加基本的SpringBoot imports
    if (!filteredImports.some(imp => imp.includes('org.springframework.stereotype.Service'))) {
      lines.push('import org.springframework.stereotype.Service;');
    }
    if (!filteredImports.some(imp => imp.includes('org.springframework.beans.factory.annotation.Autowired'))) {
      lines.push('import org.springframework.beans.factory.annotation.Autowired;');
    }
    
    filteredImports.forEach(imp => lines.push(imp));
    lines.push('');
    
    // 类注释
    lines.push('/**');
    lines.push(` * ${this.generateServiceDescription(serviceName, methods)}`);
    lines.push(' * 从大型Service中拆分而来');
    lines.push(' */');
    
    // 类注解
    lines.push('@Service');
    lines.push(`public class ${serviceName} {`);
    lines.push('');
    
    // 字段 - 只包含当前Service需要的字段
    const requiredFields = this.getRequiredFields(fields, methods);
    requiredFields.forEach(field => {
      lines.push(`    ${field.trim()}`);
    });
    
    if (requiredFields.length > 0) {
      lines.push('');
    }
    
    // 业务方法
    methods.forEach(method => {
      // 添加方法注释
      lines.push('    /**');
      lines.push(`     * ${method.name} - ${this.getMethodDescription(method)}`);
      lines.push('     */');
      
      // 添加方法内容
      const methodLines = method.content.split('\n');
      methodLines.forEach(line => {
        lines.push(line);
      });
      lines.push('');
    });
    
    // 相关的辅助方法
    const relevantHelperMethods = helperMethods.filter(helper => 
      methods.some(method => method.content.includes(helper.name))
    );
    
    if (relevantHelperMethods.length > 0) {
      lines.push('    // 辅助方法');
      relevantHelperMethods.forEach(helper => {
        const helperLines = helper.content.split('\n');
        helperLines.forEach(line => {
          lines.push(line);
        });
        lines.push('');
      });
    }
    
    lines.push('}');
    
    return lines.join('\n');
  }

  private getRequiredImports(methods: ServiceMethod[], helperMethods: ServiceMethod[]): string[] {
    const imports = new Set<string>();
    
    const allMethods = [...methods, ...helperMethods];
    
    allMethods.forEach(method => {
      const content = method.content;
      
      // Java基础类
      if (content.includes('List<') || content.includes('ArrayList<')) imports.add('java.util');
      if (content.includes('Map<') || content.includes('HashMap<')) imports.add('java.util');
      if (content.includes('Set<') || content.includes('HashSet<')) imports.add('java.util');
      if (content.includes('LocalDateTime')) imports.add('java.time.LocalDateTime');
      if (content.includes('BigDecimal')) imports.add('java.math.BigDecimal');
      
      // Spring相关
      if (content.includes('@Autowired')) imports.add('org.springframework.beans.factory.annotation.Autowired');
      if (content.includes('@Service')) imports.add('org.springframework.stereotype.Service');
      if (content.includes('@Transactional')) imports.add('org.springframework.transaction.annotation.Transactional');
    });
    
    return Array.from(imports);
  }

  private getRequiredFields(allFields: string[], methods: ServiceMethod[]): string[] {
    const requiredFields: string[] = [];
    
    allFields.forEach(field => {
      const fieldName = this.extractFieldName(field);
      if (fieldName) {
        const isUsed = methods.some(method => 
          method.content.includes(fieldName + '.') || method.content.includes(fieldName + ';')
        );
        
        if (isUsed) {
          requiredFields.push(field);
        }
      }
    });
    
    return requiredFields;
  }

  private extractFieldName(field: string): string | null {
    const match = field.match(/(?:private|public|protected)\s+\w+\s+(\w+)/);
    return match ? match[1] : null;
  }

  private generateServiceDescription(serviceName: string, methods: ServiceMethod[]): string {
    const methodNames = methods.map(m => m.name).join(', ');
    return `${serviceName.replace('Service', '')}相关业务逻辑处理服务 - 包含: ${methodNames}`;
  }

  private getMethodDescription(method: ServiceMethod): string {
    if (method.name.startsWith('create')) return '创建操作';
    if (method.name.startsWith('get') || method.name.startsWith('find')) return '查询操作';
    if (method.name.startsWith('update')) return '更新操作';
    if (method.name.startsWith('delete')) return '删除操作';
    if (method.name.startsWith('process')) return '处理操作';
    if (method.name.startsWith('send')) return '发送操作';
    return '业务操作';
  }
}